package com.sum.slike;


import com.sum.slike.utils.AttrUtils;
import com.sum.slike.utils.LogUtil;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.render.Canvas;
import ohos.agp.render.PixelMapHolder;
import ohos.app.Context;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.eventhandler.InnerEvent;
import ohos.global.resource.Resource;
import ohos.media.image.ImageSource;
import ohos.media.image.PixelMap;

import java.lang.ref.WeakReference;
import java.util.List;
/**
 * @author: zhu_zhonglin
 * @time: 2021/4/26
 */
public class SuperLikeLayout extends Component implements AnimationEndListener, Component.DrawTask {

    private static final String TAG = "SuperLikeLayout";

    private static final long INTERVAL = 40;
    private static final int MAX_FRAME_SIZE = 16;
    private static final int ERUPTION_ELEMENT_AMOUNT = 4;
    private AnimationFramePool animationFramePool;

    private AnimationHandler animationHandler;
    private BitmapProvider.Provider provider;
    private boolean hasEruptionAnimation;
    private boolean hasTextAnimation;


    public SuperLikeLayout(Context context) {
        this(context, null);
    }

    public SuperLikeLayout(Context context, AttrSet attrs) {
        this(context, attrs, 0);
    }

    public SuperLikeLayout(Context context, AttrSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        addDrawTask(this);
        init(context, attrs, defStyleAttr);
    }

    private void init(Context context, AttrSet attrs, int defStyleAttr) {
        animationHandler = new AnimationHandler(EventRunner.getMainEventRunner(), this);
        int elementAmount = AttrUtils.getIntegerFromAttr(attrs, "eruption_element_amount", ERUPTION_ELEMENT_AMOUNT);
        int maxFrameSize = AttrUtils.getIntegerFromAttr(attrs, "max_eruption_total", MAX_FRAME_SIZE);
        hasEruptionAnimation = AttrUtils.getBooleanFromAttr(attrs, "show_emoji", true);
        hasTextAnimation = AttrUtils.getBooleanFromAttr(attrs, "show_text", true);

//        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SuperLikeLayout, defStyleAttr, 0);
//        int elementAmount = a.getInteger(R.styleable.SuperLikeLayout_eruption_element_amount, ERUPTION_ELEMENT_AMOUNT);
//        int maxFrameSize = a.getInteger(R.styleable.SuperLikeLayout_max_eruption_total, MAX_FRAME_SIZE);
//        hasEruptionAnimation = a.getBoolean(R.styleable.SuperLikeLayout_show_emoji, true);
//        hasTextAnimation = a.getBoolean(R.styleable.SuperLikeLayout_show_text, true);

        animationFramePool = new AnimationFramePool(maxFrameSize, elementAmount);
    }

    @Override
    public void onDraw(Component component, Canvas canvas) {
        if (!animationFramePool.hasRunningAnimation())
            return;
        //遍历所有AnimationFrame 并绘制Element
        // note: 需要倒序遍历 nextFrame方法可能会改变runningFrameList Size 导致异常
        List<AnimationFrame> runningFrameList = animationFramePool.getRunningFrameList();
        for (int i = runningFrameList.size() - 1; i >= 0; i--) {
            AnimationFrame animationFrame = runningFrameList.get(i);
            List<Element> elementList = animationFrame.nextFrame(INTERVAL);
            for (Element element : elementList) {
                PixelMapHolder holder = new PixelMapHolder(element.getBitmap());
//                LogUtil.loge(TAG, "element:" + (element == null));
                LogUtil.loge(TAG, "paint:" + (element.getPaint() == null));

                canvas.drawPixelMapHolder(holder, element.getX(), element.getY(), element.getPaint());
            }
        }
    }

    private PixelMap convertResToPixelMap(int drawableRes) {
        PixelMap bitmap = null;
        try {
            Resource resource = mContext.getResourceManager().getResource(drawableRes);
            ImageSource imageSource = ImageSource.create(resource, null);
            bitmap = imageSource.createPixelmap(null);
            return bitmap;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return bitmap;
    }

    /**
     * 启动
     * @param x x
     * @param y y
     */
    public void launch(int x, int y) {
        if (!hasEruptionAnimation && !hasTextAnimation) {
            return;
        }
        // 喷射动画
        if (hasEruptionAnimation) {
            AnimationFrame eruptionAnimationFrame = animationFramePool.obtain(EruptionAnimationFrame.TYPE);
            if (eruptionAnimationFrame != null && !eruptionAnimationFrame.isRunning()) {
                eruptionAnimationFrame.setAnimationEndListener(this);
                eruptionAnimationFrame.prepare(x, y, getProvider());
            }
        }
        // combo动画
        if (hasTextAnimation) {
            AnimationFrame textAnimationFrame = animationFramePool.obtain(TextAnimationFrame.TYPE);
            if (textAnimationFrame != null) {
                textAnimationFrame.setAnimationEndListener(this);
                textAnimationFrame.prepare(x, y, getProvider());
            }
        }

        animationHandler.removeEvent(AnimationHandler.MESSAGE_CODE_REFRESH_ANIMATION);
        animationHandler.sendEvent(AnimationHandler.MESSAGE_CODE_REFRESH_ANIMATION, INTERVAL);

    }

    /**
     * 判断是否有动画在执行
     * @return 是否有动画在执行
     */
    public boolean hasAnimation() {
        return animationFramePool.hasRunningAnimation();
    }

    /**
     * 设置Provider
     * @param provider provider
     */
    public void setProvider(BitmapProvider.Provider provider) {
        this.provider = provider;
    }

    /**
     * 获取Provider
     * @return Provider
     */
    public BitmapProvider.Provider getProvider() {
        if (provider == null) {
            provider = new BitmapProvider.Builder(getContext())
                    .build();
        }
        return provider;
    }


    /**
     * 回收SurpriseView  添加至空闲队列方便下次使用
     *
     * @param animationFrame
     */
    private void onRecycle(AnimationFrame animationFrame) {
        LogUtil.loge(TAG, "=== AnimationFrame recycle ===");
        animationFrame.reset();
        animationFramePool.recycle(animationFrame);
    }

    @Override
    public void release() {
        super.release();
        if (!hasAnimation())
            return;
        // 回收所有动画 并暂停动画
        animationFramePool.recycleAll();
        animationHandler.removeEvent(AnimationHandler.MESSAGE_CODE_REFRESH_ANIMATION);
    }

    @Override
    public void onAnimationEnd(AnimationFrame animationFrame) {
        onRecycle(animationFrame);
    }

    /**
     *
     */
    private static final class AnimationHandler extends EventHandler {
        public static final int MESSAGE_CODE_REFRESH_ANIMATION = 1001;
        private WeakReference<SuperLikeLayout> weakReference;

        public AnimationHandler(EventRunner runner, SuperLikeLayout superLikeLayout) throws IllegalArgumentException {
            super(runner);
            weakReference = new WeakReference<>(superLikeLayout);
        }


        @Override
        protected void processEvent(InnerEvent event) {
            super.processEvent(event);
            if (event.eventId == MESSAGE_CODE_REFRESH_ANIMATION && weakReference != null && weakReference.get() != null) {
                weakReference.get().invalidate();
                // 动画还未结束继续刷新
                if (weakReference.get().hasAnimation()) {
                    sendEvent(MESSAGE_CODE_REFRESH_ANIMATION, INTERVAL);
                }
            }
        }
    }

}
